package com.citywithincity.utils;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.util.ByteArrayBuffer;

import com.citywithincity.api.ApiBuildConfig;



public class HttpUtil {
	
	public static final String DEFAULT_ENCODING = ApiBuildConfig.DEFAULT_ENCODING;
	
	public static int READ_TIMEOUT = 24000;
	public static int CONNECT_TIMEOUT = 12000;
	
	
	private static Log log = LogFactory.getLog(HttpUtil.class);
	
	public static HttpURLConnection connect(String url, String content) throws IOException {
		return connect(url, content,DEFAULT_ENCODING);
	}
	public static HttpURLConnection connect(String url, String content,String encoding) throws IOException {
		byte[] bytes = StringUtils.isEmpty(content) ? null : content.getBytes(encoding);
		return connect(url, bytes,encoding);
	}
	
	
	//private static String cookie;
	public static HttpURLConnection connect(String url, byte[] content,String encoding) throws IOException {
		HttpURLConnection connection = createConnection(url,encoding,content!=null?content.length:0);
		DataOutputStream out = null;
		try{
			//write
			if(content!=null){
				out = new DataOutputStream(connection.getOutputStream());
				out.write(content);
				out.flush();
			}
			return connection;
		}finally{
			IoUtil.close(out);
		}
		
	}
	public static void send(HttpURLConnection connection, String content) throws IOException {
		DataOutputStream out = null;
		try{
			//write
			if(content!=null){
				out = new DataOutputStream(connection.getOutputStream());
				out.write(content.getBytes(ApiBuildConfig.DEFAULT_ENCODING));
				out.flush();
			}
		}finally{
			IoUtil.close(out);
		}
	}
	
	
	
	public static HttpURLConnection createConnection(String url,String encoding,int length) throws IOException{
		URL postUrl = new URL(url);
		HttpURLConnection connection = null;
		if(url.startsWith("https")){
			HttpsURLConnection httpsURLConnection = (HttpsURLConnection) postUrl.openConnection();
			HttpsUtil.setConnections(httpsURLConnection);
			connection = httpsURLConnection;
		}else{
			connection = (HttpURLConnection) postUrl.openConnection();
		}
		
	
		connection.setDoInput(true);
		connection.setUseCaches(false);
		connection.setInstanceFollowRedirects(true);
		connection.setRequestProperty("Accept-Charset", encoding);
		if(length>0){
			connection.setRequestMethod("POST");
			connection.setRequestProperty("Content-Length", String.valueOf(length));
			connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
			connection.setDoOutput(true);
		}else{
			connection.setRequestMethod("GET");
		}
		//connection.setChunkedStreamingMode(5);
		connection.setConnectTimeout(CONNECT_TIMEOUT);
		connection.setReadTimeout(READ_TIMEOUT);
		
		return connection;
	}
	/*
	private static Map<String, Object> getJson(String url, String content) throws  IOException{
		logContent(url, content);
		HttpURLConnection connection = null;
		InputStream inputStream = null;
		try{
			connection = connect(url, content);
			if(connection.getResponseCode()==200){
				inputStream = connection.getInputStream();
				Map<String, Object> json = JsonUtil.read(inputStream);
				log.info(MapUtil.toString(json));
				return json;
			}
			String error = readError(connection);
			throw new IOException(error);
		}finally{
			IoUtil.close(inputStream);
		}
	}*/
	
	public static String readError(HttpURLConnection connection) throws IOException{
		BufferedReader reader = null;
		try{
			reader = new BufferedReader(new InputStreamReader(connection.getErrorStream(),DEFAULT_ENCODING));
			String line;
			StringBuilder sb = new StringBuilder();
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			String result = sb.toString();
			log.error(result);
			reader.close();
			return sb.toString();
		}finally{
			IoUtil.close(reader);
		}
		
	}
	/*
	private static StringBuilder logContent(String url, String content){
		if(content!=null){
			StringBuilder sb = new StringBuilder();
			sb.append("Start post:").append(url).append(" data:").append(content);
			log.info(sb.toString());
			return sb;
		}
		
		
		StringBuilder sb = new StringBuilder();
		sb.append("Start post:").append(url).append(" data:null");
		log.info(sb.toString());
		return sb;
	
		
	}
	*/
	
	public static String rawPost(String url, String content) throws IOException{
		return rawPost(url, content, DEFAULT_ENCODING);
	}
	
	public static String rawPost(String url, String content,String encoding) throws  IOException{
		StringBuilder sb = new StringBuilder();
		HttpURLConnection connection = null;
		BufferedReader reader = null;
		sb.setLength(0);
		
		log.info( "Post " + ( content!=null ?  (content.length() > 2000 ? content.substring(0,2000) : content)  : content  ));
		
		try{
			connection = connect(url, content,encoding);
			if(connection.getResponseCode()==200){
				reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),encoding));
				String line;
				while ((line = reader.readLine()) != null) {
					sb.append(line);
				}
				String result = sb.toString();
				log.info("Recv : " + (result.length() > 2000 ? result.substring(0, 2000) : result) );
				return result;
			}
			String error = readError(connection);
			throw new IOException(error);
		}finally{
			if(reader!=null){
				try{reader.close();}catch(IOException e){}
			}
		}
	}
	public static String get(String url) throws IOException {
		return get(url, DEFAULT_ENCODING);
	}

	
	
	public static String get(String url,String encoding) throws IOException {
		HttpURLConnection connection = null;
		BufferedReader reader = null;
		try{
			connection = createConnection(url,encoding,0);
			reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String line;
			StringBuffer sb = new StringBuffer();
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			log.info(sb.toString());
			return sb.toString();
		}finally{
			if(reader!=null)try{reader.close();}catch (Exception e) {}
		}
	}
	public static Map<String, Object> getJson(String url) throws IOException {
		return getJson(url,DEFAULT_ENCODING);
	}
	
	public static byte[] download(String url,String content) throws IOException{
		StringBuilder sb = new StringBuilder();// logContent(url,content);
		HttpURLConnection connection = null;
		BufferedReader reader = null;
		sb.setLength(0);
		try{
			connection = connect(url, content,DEFAULT_ENCODING);
			if(connection.getResponseCode()==200){
				int length = connection.getContentLength();
				if(length<=0){
					
					ByteArrayBuffer buffer = new ByteArrayBuffer(100000);
					
					
					byte[] bytes = new byte[1024];
					InputStream is = connection.getInputStream();
					while(true){
						int read = is.read(bytes);
						if(read<=0){
							break;
						}
						buffer.append(bytes, 0, read);
					}
					return buffer.toByteArray();
					
				}else{
					byte[] bytes = new byte[length];
					int readed = 0;
					InputStream is = connection.getInputStream();
					while(readed < bytes.length){
						int read = is.read(bytes);
						if(read<=0){
							break;
						}
						readed += read;
					}
					return bytes;
				}
				
			}
			String error = readError(connection);
			throw new IOException(error);
		}finally{
			if(reader!=null){
				try{reader.close();}catch(IOException e){}
			}
		}
		
	}
	
	public static Map<String, Object> getJson(String url,String encoding) throws IOException {
		HttpURLConnection connection = null;
		InputStream inputStream = null;
		try{
			log.info("Start post:"+url);
			connection = createConnection(url,encoding,0);
			inputStream = connection.getInputStream();
			Map<String, Object> data = JsonUtil.read(inputStream);
			log.info(MapUtil.toString(data));
			return data;
		}finally{
			if(inputStream!=null)try{inputStream.close();}catch (Exception e) {}
		}
	}
	
	
	
}
